/************************************************************************/
// Copyright (C) 2016, han_gangbiao. All rights reserved.
// Use of this source code is governed by a GPL-v2 license that can be found in the License file.
// 
// [Time]:      2016-1-4 21:53:17
// [Author]:    han_gangbiao [http://my.oschina.net/jackhen]
// [Info]:      
/************************************************************************/

namespace netos {
	SOCK_FD socket( int addr_family, int type, int protocol )
	{
	    SOCK_FD fd  = ::socket(addr_family, type, protocol);
	    if(fd < 0)
	        fd = INVALID_SOCKET_FD;
	    return fd;
	}
	
	SOCK_FD accept( SOCK_FD fd, struct sockaddr* addr, int* addrlen )
	{
	#ifdef OS_WIN
	    SOCK_FD fd_new = ::accept(fd, addr, addrlen);
	#else
	    SOCK_FD fd_new = ::accept(fd, addr, (socklen_t*)addrlen);
	#endif
	    if(fd_new < 0)
	        fd_new = INVALID_SOCKET_FD;
	    return fd_new;
	}
	
	int listen( SOCK_FD fd, int backlog )
	{
	    return ::listen(fd, backlog);
	}
	
	int bind( SOCK_FD fd, const struct sockaddr* addr, int addrlen )
	{
	    return ::bind(fd, addr, addrlen);
	}
	
	int connect( SOCK_FD fd, const struct sockaddr* addr, int addrlen )
	{
	    return ::connect(fd, addr, addrlen);
	}
	
	int getpeername( SOCK_FD fd, struct sockaddr* addr, int* addrlen )
	{
	#ifdef OS_WIN
	    return ::getpeername(fd, addr, addrlen);
	#else
	    return ::getpeername(fd, addr, (socklen_t*)addrlen);
	#endif
	}
	
	int getsockname( SOCK_FD fd, struct sockaddr* addr, int* addrlen )
	{
	#ifdef OS_WIN
	    return ::getsockname(fd, addr, addrlen);
	#else
	    return ::getsockname(fd, addr, (socklen_t*)addrlen);
	#endif
	}
	
	int recv( SOCK_FD fd, char* buf, int len, int flags /*= 0 */ )
	{
	    return ::recv(fd, buf, len, flags);
	}
	
	int send( SOCK_FD fd, const char* buf, int len, int flags /*= 0 */ )
	{
	    return ::send(fd, buf, len, flags);
	}
	
	int recvfrom( SOCK_FD fd, char* buf, int len, int flags, struct sockaddr* from, int* fromlen )
	{
	#ifdef OS_WIN
	    return ::recvfrom(fd, buf, len, flags, from, fromlen);
	#else
	    return ::recvfrom(fd, buf, len, flags, from, (socklen_t*)fromlen);
	#endif
	}
	
	int sendto( SOCK_FD fd, const char* buf, int len, int flags, const struct sockaddr* to, int tolen )
	{
	    return ::sendto(fd, buf, len, false, to, tolen);
	}
	
	int setsockopt( SOCK_FD fd, int level, int optname, const char* optval, int optlen )
	{
	    return ::setsockopt(fd, level, optname, optval, optlen);
	}
	
	int getsockopt( SOCK_FD fd, int level, int optname, char* optval, int* optlen )
	{
	#ifdef OS_WIN
	    return ::getsockopt(fd, level, optname, optval, optlen);
	#else
	    return ::getsockopt(fd, level, optname, optval, (socklen_t*)optlen);
	#endif
	}
	
	int closesocket( SOCK_FD fd )
	{
	#ifdef OS_WIN
	    return ::closesocket(fd);
	#else
	    return ::close(fd);
	#endif
	}
	
	int shutdown( SOCK_FD fd, int how )
	{
	    return ::shutdown(fd, how);
	}
	
	int ioctl_nonblock( SOCK_FD fd )
	{
	#ifdef OS_WIN
	    unsigned long ul = 1;
	    if( ::ioctlsocket(fd, FIONBIO, &ul) != 0 )
	    {
	        return -1;
	    }
	#else
	    int flags = 0;
	    if( (flags = fcntl(fd, F_GETFL, 0)) == -1 )
	    {
	        return -1;
	    }
	    if( fcntl(fd, F_SETFL, flags|O_NONBLOCK) == -1 )
	    {
	        return -1;
	    }
	#endif
	
	    return 0;
	}

} //~netos
